import { addP2D, KK_ZERO, KKP2D, KKP2DTable, KKSize, ZERO_SIZE } from "@coldcloude/kakera"
import { buildUINodeEx } from "./lib/kakera-cocos/scripts/NodeEx";
import { K2DU, KListNode } from "@coldcloude/kai2";
import { GCTD_CFG, TN_PISTOL, TN_SHOTGUN } from "./Constant";

export type K$<T> = KListNode<T>;

export class AreaTable<T> {
    step:number;
    map = new KKP2DTable<KKP2DTable<T>>();
    constructor(step:number){
        this.step = step|0;
    }
    area(pos:KKP2D):KKP2D[]{
        const x = pos.x>>this.step;
        const y = pos.y>>this.step;
        return [
            {x:x-1,y:y},   {x:x,y:y},
            {x:x-1,y:y-1}, {x:x,y:y-1}
        ];
    }
    put(pos:KKP2D,val:T){
        for(const p of this.area(pos)){
            this.map.computeIfAbsent(p,()=>new KKP2DTable<T>()).set(pos,val);
        }
    }
    remove(pos:KKP2D){
        for(const p of this.area(pos)){
            const m = this.map.get(p);
            if(m){
                m.get(pos,true);
            }
        }
    }
    getAll(pos:KKP2D):KKP2DTable<KKP2DTable<T>>{
        const rr = new KKP2DTable<KKP2DTable<T>>();
        for(const p of this.area(pos)){
            const m = this.map.get(p);
            if(m){
                rr.set(p,m);
            }
        }
        return rr;
    }
}

export const G_INVALID = 0;
export const G_VALID = 1;
export const G_USED = 2;

export class GCTDBoard {
    size:KKSize;
    grids:number[];
    constructor(size:KKSize,init?:{
        square?: {
            position: KKP2D,
            size: KKSize
        },
        grids?: number[]
    }){
        this.size = size;
        if(init&&init.grids){
            this.grids = [...init.grids];
        }
        else {
            this.grids = [];
            const initPos = init?init.square?init.square.position:KK_ZERO:KK_ZERO;
            const initSize = init?init.square?init.square.size:ZERO_SIZE:ZERO_SIZE;
            for(let y=0; y<size.height; y++){
                for(let x=0; x<size.width; x++){
                    const v = x>=initPos.x&&x<initPos.x+initSize.width&&y>=initPos.y&&y<initPos.y+initSize.height?G_VALID:G_INVALID;
                    this.grids.push(v);
                }
            }
        }
    }
    _index(pos:KKP2D){
        const x = Math.max(0,Math.min(this.size.width-1,pos.x));
        const y = Math.max(0,Math.min(this.size.height-1,pos.y));
        return y*this.size.height+x;
    }
    setP(pos:KKP2D,v:number){
        const i = this._index(pos);
        this.grids[i] = v;
    }
    getP(pos:KKP2D){
        const i = this._index(pos);
        return this.grids[i];
    }
    testBlock(pos:KKP2D,shape:KKP2D[],value:number){
        let valid = true;
        for(const d of shape){
            const v = this.getP(addP2D(pos,d));
            if(v!==value){
                valid = false;
                break;
            }
        }
        return valid;
    }
    setBlock(pos:KKP2D,shape:KKP2D[],v:number){
        for(const d of shape){
            this.setP(addP2D(pos,d),v);
        }
    }
}

export const C_TOWER = 1;
export const C_SHAPE = 2;

export type GCTDCandidateConfig = {
    category: number,
    type: string
};

export type GCTDTower = {
    type:string;
    level:number;
};

export const BN_NORMAL = "normal";

export function combineTower(src:GCTDTower,target:GCTDTower):boolean{
    let r = false;
    if(src.type===target.type&&src.level===target.level){
        target.level++;
        r = true;
    }
    return r;
}

export function createNode(){
    return buildUINodeEx();
}
